﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SweetSurvey.Controllers;
using SweetSurvey.Models;
using SweetSurvey.Models.Repositories;
using SweetSurvey.Models.ViewModels;

namespace SweetSurvey.Tests.ControllerTests
{
    /// <summary>
    ///This is a test class for AnswerControllerTest and is intended
    ///to contain all AnswerControllerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class AnswerControllerTest : ControllerTestBase
    {
        /// <summary>
        ///A test for SubmitAnswers
        ///</summary>
        [TestMethod]
        public void SubmitAnswersTest()
        {
            // variables
            var participatorId = "fakeParticipatorId";
            var optionId = "fakeOptionId";
            var count = 10;
            Expression<Func<IParticipatorRepository, string>> createParticipatorExpression = (r => r.Create(It.IsAny<Participator>()));
            Expression<Func<IAnswerRepository, string>> createAnswerExpression = (r => r.Create(It.IsAny<Answer>()));
            Expression<Func<IOptionRepository, IQueryable<Option>>> getOptionsExpression = (r => r.GetOptionsByQuestionId(It.IsAny<string>()));
            var answers = new List<AnswerViewModel>();
            for (var i = 0; i < count; i++) { answers.Add(new AnswerViewModel() { SelectedIndex = 0 }); }

            // prepare
            var mockParticipatorRepository = new Mock<IParticipatorRepository>(MockBehavior.Strict);
            mockParticipatorRepository.Setup(createParticipatorExpression).Returns(participatorId);
            var mockAnswerRepository = new Mock<IAnswerRepository>(MockBehavior.Strict);
            mockAnswerRepository.Setup(createAnswerExpression).Returns(string.Empty);
            var mockOptionRepository = new Mock<IOptionRepository>(MockBehavior.Strict);
            mockOptionRepository.Setup(getOptionsExpression).Returns(() =>
            {
                var list = new List<Option>();
                list.Add(new Option() { Id = optionId });
                return list.AsQueryable<Option>();
            });
            var controller = new AnswerController(mockParticipatorRepository.Object, mockAnswerRepository.Object, mockOptionRepository.Object);

            // act
            var result = controller.SubmitAnswers(null, (new JavaScriptSerializer()).Serialize(answers));

            // assert
            mockParticipatorRepository.Verify(createParticipatorExpression);
            mockAnswerRepository.Verify(createAnswerExpression, Times.Exactly(count));
            mockOptionRepository.Verify(getOptionsExpression, Times.Exactly(count));
            Assert.IsInstanceOfType(result, typeof(JsonResult));
        }
    }
}
